package org.jeecg.common.fs.impl;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.fs.FileDataInfo;
import org.jeecg.common.fs.FileExtInfo;
import org.jeecg.common.fs.FileServiceManager;
import org.jeecg.common.fs.IFileServiceApapter;
import org.jeecg.common.util.Md5Util;
import org.jeecg.common.util.DateUtil;
import org.jeecg.common.util.FileUtil;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Date;
import java.util.UUID;

/**
 * 本地文件上传
 */
@Slf4j
public class LocalFileServiceImpl implements IFileServiceApapter {
    private static final String storeType = "LOCAL";
    private static final String ID_PREFIX = "n.1";
    private String localPath;

    public LocalFileServiceImpl(String localPath) {
        this.localPath = localPath;
        FileServiceManager.registerService(storeType, this);
    }

    @Override
    public String getStoreType() {
        return storeType;
    }

    @Override
    public Object getConfig() {
        JSONObject config = new JSONObject();
        config.put("localPath", this.localPath);
        return config;
    }

    /**
     * 获取文件存储路径
     * @param fileName
     * @return
     */
    private String getFilePath(String fileName, FileExtInfo ext){
       String basePath = this.localPath;
       if(StringUtils.isBlank(basePath)){
           throw new JeecgBootException("附件根目录不能为空。");
       }

       if(!new File(this.localPath).exists()){
           throw new JeecgBootException("附件根目录不存在， Path=" + this.localPath);
       }

       String fileSuffix = fileName.substring(fileName.lastIndexOf("."));
       String newFileName = UUID.randomUUID().toString().replace("-", "") + fileSuffix;
       String filePath = ID_PREFIX + File.separator;
       if(StringUtils.isNotBlank(ext.getTableName())){
            filePath += ext.getTableName() + File.separator;
       }

       if(StringUtils.isNotBlank(ext.getString("partName"))){
           // 兼容数据迁移
           filePath += ext.getString("partName").replace("_", "/");
       } else {
           filePath += DateUtil.formateDate(new Date(), "yyyy") + File.separator;
           filePath += DateUtil.formateDate(new Date(), "MM") + File.separator;
           filePath += DateUtil.formateDate(new Date(), "dd") + File.separator;
       }
       filePath += newFileName + "." + fileSuffix;
       return ID_PREFIX + filePath;
    }

    @Override
    public String uploadFile(String path, FileExtInfo ext) {
        return this.uploadFile(new File(path), ext);
    }

    @Override
    public String uploadFile(InputStream is, String fileName, FileExtInfo ext) {
        String fileId = null;
        OutputStream os = null;
        try{
            fileId = this.getFilePath(fileName, ext);
            String storeFile = this.localPath + fileId;
            FileUtil.mkdirs(new File(storeFile).getParent());
            os = new FileOutputStream(storeFile);

            int len = 0;
            long totalLen = 0;
            byte[] bytes = new byte[1024];
            while((len = is.read(bytes)) != -1){
                os.write(bytes, 0, len);
                totalLen += len;
            }

            if(totalLen <= 0){
                throw new JeecgBootException("文件大小为0，保存失败");
            }
            os.flush();
        } catch (Exception e){
            log.error("上传文件失败, fileName=" + fileName, e);
            throw new JeecgBootException("上传文件失败");
        } finally {
            try{
                if(os != null){
                    os.close();
                }
            } catch (Exception e){}

            try{
                if(is != null){
                    is.close();
                }
            } catch (Exception e){}
        }
        return fileId;
    }

    @Override
    public String uploadFile(File file, FileExtInfo ext) {
        String fileId = null;
        InputStream is = null;
        try{

            is = new FileInputStream(file);
            fileId = this.uploadFile(is, file.getName(), ext);
        } catch (Exception e){
            throw new JeecgBootException(e);
        } finally {
            try{
                if(is != null){
                    is.close();
                }
            } catch (Exception e){}
        }
        return fileId;
    }

    @Override
    public String uploadContent(String content, FileExtInfo ext) {
        String fileId = null;
        OutputStream os = null;
        OutputStreamWriter osWriter = null;
        try{
            fileId = this.getFilePath("content.txt", ext);
            String storeFile = this.localPath + fileId;
            FileUtil.mkdirs(new File(storeFile).getParent());
            os = new FileOutputStream(storeFile);
            osWriter = new OutputStreamWriter(os, "utf-8");
            ext.add("doc", content);
            osWriter.append(ext.toExtJSONString());
        } catch (Exception e){
            log.error("保存文档内容失败", e);
            throw new JeecgBootException("上传文件失败");
        } finally {
            try{
                if(osWriter != null){
                    osWriter.close();
                }
            } catch (Exception e){}

            try{
                if(os != null){
                    os.close();
                }
            } catch (Exception e){}
        }
        return fileId;
    }

    @Override
    public boolean downloadFile(String id, OutputStream os, FileExtInfo ext) {
        InputStream is = null;
        try{
            String storeFile = this.localPath + id;
            is = new FileInputStream(storeFile);

            int len = 0;
            byte[] bytes = new byte[2048];
            while((len = is.read(bytes)) != -1){
                os.write(bytes, 0, len);
            }
            os.flush();
        } catch (Exception e){
            throw new JeecgBootException("下载文件失败", e);
        } finally {
            try{
                if(os != null){
                    os.close();
                }
            } catch (Exception e){}

            try{
                if(is != null){
                    is.close();
                }
            } catch (Exception e){}
        }
        return true;
    }

    @Override
    public boolean downloadFile(String id, String path, FileExtInfo ext) {
       return this.downloadFile(id, new File(path), ext);
    }

    @Override
    public boolean downloadFile(String id, File file, FileExtInfo ext) {
        OutputStream os = null;
        try{
            os = new FileOutputStream(file);
            this.downloadFile(id, os, ext);
        } catch (Exception e){
            throw new JeecgBootException(e);
        } finally {
            try{
                if(os != null){
                    os.close();
                }
            } catch (Exception e){}
        }
        return true;
    }

    @Override
    public FileDataInfo getFileStream(String id, FileExtInfo ext) {
        FileDataInfo fileInfo = null;
        try{
            String storeFile = this.localPath + id;
            File file = new File(storeFile);
            InputStream is = new FileInputStream(file);
            fileInfo = new FileDataInfo();
            fileInfo.setId(id);
            fileInfo.setLength(file.length());
            fileInfo.setFilename(file.getName());
            fileInfo.setFilePath(storeFile);
            fileInfo.setInputStream(is);
            fileInfo.setContentType(Files.probeContentType(Paths.get(storeFile)));
            fileInfo.setCheckCode(() -> Md5Util.getMD5(storeFile) );
        } catch (Exception e){
            throw new JeecgBootException("获取文件流失败", e);
        }
        return fileInfo;
    }

    @Override
    public String getFileContent(String id, FileExtInfo ext) {
        String doc = "";
        InputStream is = null;
        BufferedReader br = null;
        try{
            String storeFile = this.localPath + id;
            is = new FileInputStream(storeFile);
            br = new BufferedReader(new InputStreamReader(is, "utf-8"));
            String line = null;
            StringBuffer strBuffer = new StringBuffer();
            while((line = br.readLine()) != null){
                strBuffer.append(line);
            }
            if(strBuffer.toString().length() > 0){
                JSONObject jsonObject = JSONObject.parseObject(strBuffer.toString());
                doc = jsonObject.getString("doc");
            }
        } catch (Exception e){
            throw new JeecgBootException("下载文件失败", e);
        } finally {
            try{
                if(br != null){
                    br.close();
                }
            } catch (Exception e){}

            try{
                if(is != null){
                    is.close();
                }
            } catch (Exception e){}
        }
        return doc;
    }

    @Override
    public void deleteFile(String id, FileExtInfo ext) {
        File file = new File(this.localPath + id);
        if(file.exists()){
            file.delete();
        }
    }
}
